package sk.uniba.fmph.asdf.gui.views;

import com.alee.laf.WebLookAndFeel;
import com.alee.laf.checkbox.WebCheckBox;
import com.alee.laf.label.WebLabel;
import com.alee.laf.text.WebPasswordField;
import com.alee.laf.text.WebTextField;
import java.io.IOException;
import java.util.prefs.Preferences;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import net.miginfocom.swing.MigLayout;
import sk.uniba.fmph.asdf.Session;
import sk.uniba.fmph.asdf.db.Account;
import sk.uniba.fmph.asdf.db.AccountManager;
import sk.uniba.fmph.asdf.exceptions.DatabaseException;
import sk.uniba.fmph.asdf.exceptions.LoginException;
import sk.uniba.fmph.asdf.exceptions.NoSuchAccountException;
import sk.uniba.fmph.asdf.exceptions.OfflineException;
import sk.uniba.fmph.asdf.exceptions.WrongPasswordException;
import sk.uniba.fmph.asdf.gui.GuiUtils;

/**
 * Prihlasovací dialog. Zobrazuje formulár na zadanie prihlasovacích údajov a
 * sprostredkuje prihlásenie.
 *
 * @author Jakub Gaľ
 */
public class LoginView extends View {

	private static final long serialVersionUID = -5674067367215457379L;
	private JButton loginBtn;
	private JButton registerBtn;
	private WebTextField usernameField;
	private WebPasswordField passwordField;
	private WebCheckBox rememberLoginCheckBox;

	/**
	 * Vytvori view a inicializuje komponenty.
	 *
	 * @param parent
	 */
	public LoginView() {
		super(JFrame.EXIT_ON_CLOSE);
		initComponents();
	}

	@Override
	protected final void initComponents() {
		setTitle("Prihlásenie");

		getContentPane().setLayout(new MigLayout());

		WebLabel usernameLabel = GuiUtils.getShadedLabel("Prihlasovacie meno");
		WebLabel passwordLabel = GuiUtils.getShadedLabel("Heslo");

		usernameField = new WebTextField(Session.getPreferences().get("username", null));
		usernameField.setMargin(0, 2, 0, 0);
		usernameField.setLeadingComponent(GuiUtils.getImage("username"));

		passwordField = new WebPasswordField(Session.getPreferences().get("password", null));
		passwordField.setMargin(0, 2, 0, 0);
		passwordField.setLeadingComponent(GuiUtils.getImage("password"));

		rememberLoginCheckBox = new WebCheckBox("Zapamätať prihlasovacie údaje", Session.getPreferences().getBoolean("rememberLogin", false));

		registerBtn = new JButton("Vytvoriť účet...", GuiUtils.getIcon("sign_up"));
		registerBtn.addActionListener(this);

		loginBtn = new JButton("Prihlásiť", GuiUtils.getIcon("sign_in"));
		loginBtn.addActionListener(this);
		getRootPane().setDefaultButton(loginBtn);

		add(usernameLabel, "wrap");
		add(usernameField, "grow, wrap");
		add(passwordLabel, "wrap");
		add(passwordField, "grow, wrap");
		add(rememberLoginCheckBox, "wrap");
		add(registerBtn, "split 2");
		add(loginBtn);

		usernameField.requestFocusInWindow();
	}

	@Override
	public void actionPerformed(java.awt.event.ActionEvent evt) {
		if (evt.getSource() == loginBtn) {
			login();
		} else if (evt.getSource() == registerBtn) {
			showRegistrationView();
		}
	}

	/**
	 * Spracovanie kliknutia na tlacidlo Prihlasit. Pokusi sa pouzivatela
	 * prihlasit. Ak dojde k vynimke, zobrazi chybovy dialog, inak ulozi do triedy
	 * Session udaje o pouzivatelovi.
	 *
	 */
	private void login() {
		Account account = null;
		String username = usernameField.getText();
		String password = new String(passwordField.getPassword());

		try {
			account = AccountManager.loginUser(username, password);
			Session.setOnline(true);
		} catch (NoSuchAccountException | WrongPasswordException e) {
			JOptionPane.showMessageDialog(rootPane, "Nesprávne prihlasovacie meno alebo heslo.", "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (DatabaseException e) {
			JOptionPane.showConfirmDialog(rootPane, "Prihlásenie zlyhalo pre chybu v komunikácii s databázou.", "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (OfflineException e) {
			int result = JOptionPane.showConfirmDialog(rootPane, "Nepodarilo sa pripojiť k databáze. Prajete si spustiť aplikáciu v režime offline?", "Bez pripojenia", JOptionPane.INFORMATION_MESSAGE);
			if (result == JOptionPane.OK_OPTION) {
				try {
					account = AccountManager.loginOfflineUser(username, password);
					Session.setOnline(false);
				} catch (IOException ex) {
					JOptionPane.showMessageDialog(rootPane, "Nepodarilo sa otvoriť lokálny súbor.", "Chyba!", JOptionPane.ERROR_MESSAGE);
				} catch (LoginException ex) {
					JOptionPane.showMessageDialog(rootPane, "Prihlásenie zlyhalo! Skontrolujte korektnosť zadaných prihlasovacích údajov a uistite sa, že ste sa pod týmto účtom prihlásili aspoň raz v režime online.", "Chyba!", JOptionPane.ERROR_MESSAGE);
				}
			}
		}

		if (account != null) {
			Preferences preferences = Session.getPreferences();
			if (rememberLoginCheckBox.isSelected()) {
				preferences.put("username", username);
				preferences.put("password", password);
				preferences.putBoolean("rememberLogin", true);
			} else if (Session.getPreferences().getBoolean("rememberLogin", false)) {
				preferences.remove("username");
				preferences.remove("password");
				preferences.putBoolean("rememberLogin", false);
			}

			Session.setAccount(account);
			showMainView();
			setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			closeWindow();
		}
	}

    /**
     * Zobrazenie hlavneho okna.
     */
	private void showMainView() {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				setEnabled(false);
				new MainView().display();
			}
		});
	}

    /**
     * Zobrazenie okna obsahujuceho registracny formular.
     */
	private void showRegistrationView() {
		final View thisView = this;
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				setEnabled(false);
				new RegistrationView(thisView).display();
			}
		});
	}

	public static void main(String args[]) {
		WebLookAndFeel.install();
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				new LoginView().display();
			}
		});
	}
}